package com.sky.aop;

import com.sky.anno.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 类描述：
 */
@Aspect
@Component
public class AutoFillAspect {

    @Before("@annotation(com.sky.anno.AutoFill)")
    public void autoFill(JoinPoint jp){
        //1.判断是新增还是修改
        //先获取签名，因为要增强的是方法（该注解是加在方法上的），所以可以确定是获取方法签名
        MethodSignature methodSignature = (MethodSignature) jp.getSignature();
        //获取方法签名中的方法，然后获取方法上的注解，再获取注解的value属性的值
        OperationType value = methodSignature.getMethod().getAnnotation(AutoFill.class).value();
        //获取当前方法参数，也就是实体对象
        Object[] args = jp.getArgs();
        //因为只有一个参数，所以直接获取0索引即可
        Object entity= args[0];
        //拿到实体对象entity后，通过反射拿到对应的set方法

        Method setCreateTime;
        Method setUpdateTime;
        Method setCreateUser;
        Method setUpdateUser;
        try {
            setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
            setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
        //2.如果是新增，为创建时间、更新时间、创建人、更新人赋值
        if(OperationType.INSERT== value){
            try {
                setCreateTime.invoke(entity, LocalDateTime.now());

                setUpdateTime.invoke(entity, LocalDateTime.now());

                setCreateUser.invoke(entity, BaseContext.getCurrentId());

                setUpdateUser.invoke(entity, BaseContext.getCurrentId());

            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        }
        //3.如果是修改，为更新时间、更新人赋值
        if(OperationType.UPDATE== value){
            try {
                setUpdateTime.invoke(entity, LocalDateTime.now());
                setUpdateUser.invoke(entity, BaseContext.getCurrentId());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}
